class Snake {
  // 容器
  element: HTMLElement
  // 蛇头
  head: HTMLElement
  // 蛇身
  bodies: HTMLCollection

  constructor() {
    this.element = document.querySelector('.snake')!
    this.head = document.querySelector('.snake > div') as HTMLElement
    this.bodies = this.element.getElementsByTagName('div')
  }

  get X() {
    return this.head.offsetLeft
  }

  get Y() {
    return this.head.offsetTop
  }

  set X(value: number) {
    if (this.X === value) {
      return
    }

    if (this.bodies[1] && (this.bodies[1] as HTMLElement).offsetLeft === value) {
      if (value > this.X) {
        value = this.X - 10
      } else {
        value = this.X + 10
      }
    }

    if (value < 0 || value > 290) {
      throw new Error('蛇撞墙了')
    }

    this.moveBody()

    this.head.style.left = value + 'px'
  }

  set Y(value: number) {
    // 无效操作
    if (this.Y === value) {
      return
    }
    // 阻止掉头
    if (this.bodies[1] && (this.bodies[1] as HTMLElement).offsetTop === value) {
      if (value > this.Y) {
        value = this.Y - 10
      } else {
        value = this.Y + 10
      }
    }
    if (value < 0 || value > 290) {
      throw new Error('蛇撞墙了')
    }
    // 身体移动
    this.moveBody()
    // 蛇头移动
    this.head.style.top = value + 'px'
    this.checkCrashSelf()
  }

  // 身体变长
  addBody() {
    this.element.insertAdjacentHTML("beforeend", "<div></div>")
  }

  // 移动身体
  moveBody() {
    for (let i = this.bodies.length - 1; i > 0; i--) {
      // 获取前面身体的定位
      let X = (this.bodies[i - 1] as HTMLElement).offsetLeft;
      let Y = (this.bodies[i - 1] as HTMLElement).offsetTop;

      // 设置当前身体的定位
      (this.bodies[i] as HTMLElement).style.left = X + 'px';
      (this.bodies[i] as HTMLElement).style.top = Y + 'px';
    }
  }

  // 检查自身碰撞
  checkCrashSelf() {
    for (let i = 1; i < this.bodies.length; i++) {
      let bd = this.bodies[i] as HTMLElement
      if (this.X === bd.offsetLeft && this.Y === bd.offsetTop) {
        throw new Error('咬到自身')
      }
    }
  }
}

export default Snake